#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        //这道题目的解法就是固定一个数字，然后就变成了寻找两个数字的和为一个固定值（也就是两数之和）
        //我们知道对于两数之和的题目，排序之后，通过双指针能够快速找到目标值，所以这里
        //需要使用排序进行优化
        sort(nums.begin(),nums.end());
        vector<vector<int>> ret;
        int n = nums.size();
        for(int i = 0;i<nums.size()-2;i++)
        {
            if(i&&nums[i-1] == nums[i])
            {
                continue;//防止记录相同的三元组
            }
            int target = -nums[i];
            int left = i+1;
            int right = nums.size()-1;
            //这里在排序之后有一些小的优化点
            //第一个优化点：如果i这个位置的值和i+1和i+2的值之和已经大于了0那么已经不存在任何的三元组了
            //因为i+2后面的数字和i相加只会让值变得更加的大，而不会让值变小
            if(nums[i]+nums[i+1]+nums[i+2]>0)
            {
                break;
            }
            if(nums[i]+nums[n-2]+nums[n-1]<0)
            {
                //第二个优化点
                continue;//或者是i这个位置的值和最大的两个数字之和都是小于0的，那么i这个位置的值不存在任何的
                //可能性会让和等于0
            }
            while(left<right)
            {
                int sum = nums[left]+nums[right];
                if(sum<target)
                {
                   left++;
                }
                else if(sum>target)
                {
                    right--;
                }
                else
                {
                    //找到了符合条件的三元组和
                    vector<int> tmp{nums[left],nums[right],nums[i]};
                    ret.push_back(tmp);
                    //看是否还存在其它的二元组和为target，但是为了防止出现重复依旧要进行去重
                    left++;
                    right--;
                    while(left<right)
                    {
                        if(nums[left] == nums[left-1])
                        {
                            left++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    while(left<right)
                    {
                        if(nums[right] == nums[right+1])
                        {
                            right--;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
        }
        return ret;
    }
};